home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / ADVANCED / TEXTMAP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  6.3 KB  |  283 lines

  1.  
  2. /* textmap.c - by David Blythe, SGI */
  3.  
  4. /* Helper routines used by textext.c for texture mapped fonts. */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <GL/glut.h>
  9. #include "textmap.h"
  10. #include "texture.h"
  11.  
  12. static texfnt *curtfnt;
  13. static unsigned char *fb;
  14. static unsigned char *gptr;
  15.  
  16. /* get metric data into image */
  17. static void
  18. initget(void)
  19. {
  20.   gptr = fb;
  21. }
  22.  
  23. static void
  24. getbytes(void *pbuf, int n)
  25. {
  26.   char *buf = pbuf;
  27.   while (n--)
  28.     *buf++ = *gptr++;
  29. }
  30.  
  31. static void
  32. fixrow(unsigned short *sptr, int n)
  33. {
  34.   while (n--) {
  35.     /* *sptr = *sptr + (0xff<<8); */
  36.     /* *sptr = (*sptr<<8) | 0xff; */
  37.     sptr++;
  38.   }
  39. }
  40.  
  41. texfnt *
  42. readtexfont(char *name)
  43. {
  44.   texfnt *tfnt;
  45.   unsigned *image;
  46.   unsigned char *cptr;
  47.   unsigned short *sbuf, *sptr;
  48.   short advancecell, xadvance;
  49.   short llx, lly, urx, ury, ox, oy;
  50.   int i, y, extralines;
  51.   texchardesc *cd;
  52.   int xsize, ysize, components;
  53.  
  54.   tfnt = (texfnt *) malloc(sizeof(texfnt));
  55.   image = read_texture(name, &xsize, &ysize, &components);
  56.   if (!image) {
  57.     fprintf(stderr, "textmap: can't open font image %s\n", name);
  58.     return 0;
  59.   }
  60.   extralines = ysize - xsize;
  61.   if (extralines < 1) {
  62.     fprintf(stderr, "textmap: bad input font!!\n");
  63.     return 0;
  64.   }
  65.   fb = (unsigned char *) malloc(xsize * extralines);
  66.   sbuf = (unsigned short *) malloc(xsize * sizeof(short));
  67.   cptr = fb;
  68.   for (y = xsize; y < ysize; y++) {
  69.     int x;
  70.     for (x = 0; x < xsize; x++)
  71.       cptr[x] = image[y * xsize + x] >> 16;
  72.     cptr += xsize;
  73.   }
  74.   initget();
  75.   tfnt->rasxsize = xsize;
  76.   tfnt->rasysize = xsize;
  77.   getbytes(&tfnt->charmin, sizeof(short));
  78.   getbytes(&tfnt->charmax, sizeof(short));
  79.   getbytes(&tfnt->pixhigh, sizeof(float));
  80.   getbytes(&advancecell, sizeof(short));
  81.   tfnt->nchars = tfnt->charmax - tfnt->charmin + 1;
  82.   tfnt->chars = (texchardesc *) malloc(tfnt->nchars * sizeof(texchardesc));
  83.   tfnt->rasdata = (unsigned short *) malloc(tfnt->rasxsize * tfnt->rasysize * sizeof(long));
  84.   sptr = tfnt->rasdata;
  85.   for (y = 0; y < tfnt->rasysize; y++) {
  86.     int x;
  87.     for (x = 0; x < xsize; x++)
  88.       sptr[x] = image[y * xsize + x] >> 16;
  89.     fixrow(sptr, tfnt->rasxsize);
  90.     sptr += tfnt->rasxsize;
  91.   }
  92.  
  93.   cd = tfnt->chars;
  94.   for (i = 0; i < tfnt->nchars; i++) {
  95.     getbytes(&xadvance, sizeof(short));
  96.     getbytes(&llx, sizeof(short));
  97.     getbytes(&lly, sizeof(short));
  98.     getbytes(&urx, sizeof(short));
  99.     getbytes(&ury, sizeof(short));
  100.     getbytes(&ox, sizeof(short));
  101.     getbytes(&oy, sizeof(short));
  102.     cd->movex = xadvance / (float) advancecell;
  103.  
  104.     if (llx >= 0) {
  105.       cd->haveimage = 1;
  106.       cd->llx = (llx - ox) / tfnt->pixhigh;
  107.       cd->lly = (lly - oy) / tfnt->pixhigh;
  108.       cd->urx = (urx - ox + 1) / tfnt->pixhigh;
  109.       cd->ury = (ury - oy + 1) / tfnt->pixhigh;
  110.       cd->tllx = llx / (float) tfnt->rasxsize;
  111.       cd->tlly = lly / (float) tfnt->rasysize;
  112.       cd->turx = (urx + 1) / (float) tfnt->rasxsize;
  113.       cd->tury = (ury + 1) / (float) tfnt->rasysize;
  114.       cd->data[0] = cd->tllx;
  115.       cd->data[1] = cd->tlly;
  116.  
  117.       cd->data[2] = cd->llx;
  118.       cd->data[3] = cd->lly;
  119.  
  120.       cd->data[4] = cd->turx;
  121.       cd->data[5] = cd->tlly;
  122.  
  123.       cd->data[6] = cd->urx;
  124.       cd->data[7] = cd->lly;
  125.  
  126.       cd->data[8] = cd->turx;
  127.       cd->data[9] = cd->tury;
  128.  
  129.       cd->data[10] = cd->urx;
  130.       cd->data[11] = cd->ury;
  131.  
  132.       cd->data[12] = cd->tllx;
  133.       cd->data[13] = cd->tury;
  134.  
  135.       cd->data[14] = cd->llx;
  136.       cd->data[15] = cd->ury;
  137.  
  138.       cd->data[16] = cd->llx;
  139.       cd->data[17] = cd->lly;
  140.       cd->data[18] = cd->urx;
  141.       cd->data[19] = cd->lly;
  142.  
  143.       cd->data[20] = cd->urx;
  144.       cd->data[21] = cd->ury;
  145.       cd->data[22] = cd->llx;
  146.       cd->data[23] = cd->ury;
  147.  
  148.     } else {
  149.       cd->haveimage = 0;
  150.     }
  151.     cd++;
  152.   }
  153.   free(fb);
  154.   free(sbuf);
  155.   free(image);
  156.   return tfnt;
  157. }
  158.  
  159. void
  160. texfont(texfnt * tfnt)
  161. {
  162.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  163.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  164.   glTexImage2D(GL_TEXTURE_2D, 0, 2, tfnt->rasxsize, tfnt->rasysize, 0,
  165.     GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tfnt->rasdata);
  166.   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  167.   curtfnt = tfnt;
  168. }
  169.  
  170. float
  171. texstrwidth(char *str)
  172. {
  173.   unsigned int c;
  174.   int charmin, tnchars;
  175.   texfnt *tfnt;
  176.   texchardesc *cdbase, *cd;
  177.   float xpos;
  178.  
  179.   tfnt = curtfnt;
  180.   if (!tfnt) {
  181.     fprintf(stderr, "texstrwidth: no texfont set!!\n");
  182.     return 0;
  183.   }
  184.   charmin = tfnt->charmin;
  185.   tnchars = tfnt->nchars;
  186.   cdbase = tfnt->chars;
  187.   xpos = 0.0;
  188.   while (*str) {
  189.     c = *str - charmin;
  190.     if (c < tnchars) {
  191.       cd = cdbase + c;
  192.       xpos += cd->movex;
  193.     }
  194.     str++;
  195.   }
  196.   return xpos;
  197. }
  198.  
  199. void
  200. texcharstr(char *str)
  201. {
  202.   unsigned int c;
  203.   int charmin, tnchars;
  204.   texfnt *tfnt;
  205.   texchardesc *cdbase, *cd;
  206.   float *fdata, xpos;
  207.  
  208.   tfnt = curtfnt;
  209.   if (!tfnt) {
  210.     fprintf(stderr, "texcharstr: no texfont set!!\n");
  211.     return;
  212.   }
  213.   charmin = tfnt->charmin;
  214.   tnchars = tfnt->nchars;
  215.   cdbase = tfnt->chars;
  216.   xpos = 0.0;
  217. #if 0
  218.   texbind(TX_TEXTURE_0, LETTER_INDEX);  /* bind letter texture */
  219.   tevbind(TV_ENV0, LETTER_INDEX);
  220. #endif
  221.   while (*str) {
  222.     c = *str - charmin;
  223.     if (c < tnchars) {
  224.       cd = cdbase + c;
  225.       if (cd->haveimage) {
  226.         fdata = cd->data;
  227.         fdata[16] = fdata[2] + xpos;
  228.         fdata[18] = fdata[6] + xpos;
  229.         fdata[20] = fdata[10] + xpos;
  230.         fdata[22] = fdata[14] + xpos;
  231.         glBegin(GL_POLYGON);
  232.         glTexCoord2fv(&fdata[0]);
  233.         glVertex2fv(&fdata[16]);
  234.         glTexCoord2fv(&fdata[4]);
  235.         glVertex2fv(&fdata[18]);
  236.         glTexCoord2fv(&fdata[8]);
  237.         glVertex2fv(&fdata[20]);
  238.         glTexCoord2fv(&fdata[12]);
  239.         glVertex2fv(&fdata[22]);
  240.         glEnd();
  241.       }
  242.       xpos += cd->movex;
  243.     }
  244.     str++;
  245.   }
  246. }
  247.  
  248. int
  249. texfntinit(char *file)
  250. {
  251.   static int once = 0;
  252.   static texfnt *tfnt;
  253.   if (!once) {
  254.     tfnt = readtexfont(file);
  255.     if (!tfnt) {
  256.       fprintf(stderr, "texfntinit: can't open input font %s\n", file);
  257.       return -1;
  258.     }
  259.     texfont(tfnt);
  260.     once = 1;
  261.   }
  262.   return 0;
  263. }
  264.  
  265. float
  266. texfntwidth(char *str)
  267. {
  268.   return texstrwidth(str) * 12.5 / 6.;
  269. }
  270.  
  271. void
  272. texfntstroke(char *s, float xoffset, float yoffset)
  273. {
  274.   glEnable(GL_BLEND);
  275.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  276.   glPushMatrix();
  277.   glTranslatef(xoffset, yoffset, 0.0);
  278.   glScalef(12.5, 12.5, 12.5);
  279.   texcharstr(s);
  280.   glPopMatrix();
  281.   glDisable(GL_BLEND);
  282. }
  283.